home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Light ROM 1
/
LIGHT-ROM 1 (Amiga Library Services)(1994).iso
/
ffdisks
/
d939.lha
/
ExtraCmds
/
source_etc.lha
/
src
/
DirTree.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-22
|
10KB
|
404 lines
/* --------------------------------- -------
* |\ | | | | | |.| | \| |/ /|\ |||||||
* | | | |/ | |\ |/ |/| |\ |/ | ? ---+--- =<
* | | | | | | | | | | | \qqqqqqqqq/
* --------------------------------- ~~~~~~~~~~~~~~~~
* DirTree - Prints sub-directory trees
* Copyright (C) 1992, 1993 Torsten Poulin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author can be contacted by s-mail at
* Torsten Poulin
* Banebrinken 99, 2, 77
* DK-2400 Copenhagen NV
* DENMARK
*
* Created 23-Feb-92 (Version 1)
* $Id: DirTree.c,v 37.5 93/03/01 12:52:58 Torsten Rel $
* $Log: DirTree.c,v $
* Revision 37.5 93/03/01 12:52:58 Torsten
* Changed all occurrences of "struct DosBase *" to "struct DosLibrary *"
*
* Revision 37.4 93/02/17 22:33:59 Torsten
* Fixed Enforcer problems when dealing with the no directories
* specified case.
*
* Revision 37.3 93/02/17 09:12:25 Torsten
* DIR/M is not a required argument anymore.
* Is now aware of links, but will not follow them.
* It used to think that softlinks (fib_DirEntryType == ST_SOFTLINK)
* were directories that could be entered.
* Changed the header text a bit.
* Does not AllocMem() space for filename in listnodes anymore.
* Now checks whether AllocDosObject() succeeds.
*
* Revision 37.2 93/02/12 15:15:49 Torsten
* Now responds to Ctrl-C!!! Major improvement!!!
* New switch: FILES.
*
*/
/*
* The bit-map code in this program was picked up from Dr. Dobb's
* I think, but I don't remember which volume ;-(
*
* Define LOCKALL to ensure that directories being examined
* don't disappear before we're done with them.
* The disadvantage is that we use more memory.
*/
#define LOCKALL
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/datetime.h>
#include <dos/dosasl.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include "dirtree_rev.h"
/* my include files are for V36, so ... */
#pragma libcall UtilityBase Stricmp A2 9802
LONG Stricmp(char *, char *);
#define PROGNAME "DirTree"
#define USERBREAK (-1)
#define BAR "| "
#define ELL "`---"
#define TEE "+---"
struct nameList {
struct nameList *next;
char name[108]; /* just to be safe... */
LONG type;
#ifdef LOCKALL
BPTR lock;
#endif
};
typedef struct {
struct Library *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
BOOL nohead;
BOOL files;
char Map[64 / 8];
} Global;
char const versionID[] = VERSTAG;
char const copyright[] = "$COPYRIGHT:©1992,1993 Torsten Poulin$";
static VOID setbit(Global *global, LONG c, LONG val);
static VOID print_bars(Global *global, LONG depth, LONG terminate);
static LONG printdtree(Global *global, UBYTE *dname, LONG others);
LONG dirtree(Global *global, char *dirname);
LONG entrypoint(VOID)
{
struct Library *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
Global *global;
struct RDArgs *args;
LONG arg[3];
LONG rc = RETURN_OK;
UBYTE **dir;
arg[0] = arg[1] = arg[2] = 0L;
SysBase = *(struct Library **) 4L;
if (!(global = AllocMem(sizeof(Global), MEMF_PUBLIC | MEMF_CLEAR)))
return RETURN_FAIL;
global->SysBase = SysBase;
if (!(global->DOSBase = DOSBase = (struct DosLibrary *)
OpenLibrary("dos.library", 37L)))
{
rc = RETURN_FAIL;
goto noDOS;
}
if (!(global->UtilityBase = UtilityBase =
OpenLibrary("utility.library", 37L)))
{
rc = RETURN_FAIL;
goto noUtility;
}
if (args = ReadArgs("DIR/M,NOHEAD/S,FILES/S", arg, NULL))
{
global->nohead = (BOOL) arg[1];
global->files = (BOOL) arg[2];
dir = (UBYTE **) *arg;
if (dir)
for (; *dir && rc == RETURN_OK; dir++)
rc = dirtree(global, *dir);
else
rc = dirtree(global, "");
FreeArgs(args);
}
else
{
LONG err = IoErr();
PrintFault(err, PROGNAME);
rc = RETURN_ERROR;
}
CloseLibrary(UtilityBase);
noUtility:
CloseLibrary((struct Library *) DOSBase);
noDOS:
FreeMem(global, sizeof(Global));
return rc;
}
#define testbit(x) ( global->Map[x >> 3] & (1 << (x & 0x07)) )
static VOID setbit(Global *global, LONG c, LONG val)
{
if (val)
global->Map[c >> 3] |= 1 << (c & 0x07);
else
global->Map[c >> 3] &= ~(1 << (c & 0x07));
}
static VOID print_bars(Global *global, LONG depth, LONG terminate)
{
struct DosLibrary *DOSBase = global->DOSBase;
LONG i;
for (i = 0; i < depth - 1; i++)
PutStr(testbit(i) ? BAR : " ");
if (terminate)
PutStr("\n");
}
static LONG printdtree(Global *global, UBYTE *dname, LONG others)
{
struct Library *SysBase = global->SysBase;
struct DosLibrary *DOSBase = global->DOSBase;
struct Library *UtilityBase = global->UtilityBase;
struct FileInfoBlock *m;
BPTR lock, oldlock;
static LONG depth = -1;
LONG count = 0;
LONG rc = RETURN_OK;
struct nameList *list, *p;
struct nameList *newnode;
LONG type;
BOOL OutOfMemory = FALSE;
BOOL UserBreak = FALSE;
list = NULL;
if (!(m = AllocDosObject(DOS_FIB, NULL)))
{
PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
return RETURN_FAIL;
}
if (lock = Lock(dname, SHARED_LOCK))
{
oldlock = CurrentDir(lock);
if (Examine(lock, m))
{
type = m->fib_DirEntryType;
if (type < 0 || type == ST_SOFTLINK)
{
PrintFault(ERROR_OBJECT_WRONG_TYPE, dname);
CurrentDir(oldlock);
UnLock(lock);
FreeDosObject(DOS_FIB, m);
return RETURN_WARN;
}
if (++depth)
{
print_bars(global, depth, 0);
PutStr(others ? TEE : ELL);
}
PutStr(m->fib_FileName); /* dir name */
if (global->files)
PutStr(" (dir)");
PutStr("\n");
while (ExNext(lock, m))
{
if (UserBreak = (BOOL) CheckSignal(SIGBREAKF_CTRL_C))
break;
type = m->fib_DirEntryType;
if (type < 0 && !global->files)
continue;
/* Store the directory name */
if (!(newnode = AllocMem(sizeof(struct nameList),
MEMF_PUBLIC)))
{
PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
rc = RETURN_FAIL;
OutOfMemory = TRUE;
break;
}
strcpy(newnode->name, m->fib_FileName);
newnode->type = type;
#ifdef LOCKALL
newnode->lock = Lock(m->fib_FileName, SHARED_LOCK);
#endif
/* Insert */
newnode->next = NULL;
if (list == NULL) /* insert into empty list */
list = newnode;
else
{
/* inserting into nonempty list */
p = list;
if (Stricmp(m->fib_FileName, p->name) < 0)
{
/* insert before first node */
newnode->next = list;
list = newnode;
}
else
{
/* general case */
for (; p->next; p = p->next)
if (Stricmp(m->fib_FileName, p->next->name) < 0)
break;
newnode->next = p->next;
p->next = newnode;
}
}
++count;
}
}
/* Traverse the list and free up memory */
for (p = list; p; )
{
struct nameList *remember;
remember = p;
if (!OutOfMemory && !UserBreak)
{
if (p->type >= 0 && p->type != ST_LINKDIR && p->type != ST_SOFTLINK)
{
--count;
setbit(global, depth, count);
rc = printdtree(global, p->name, count);
if (rc == USERBREAK)
UserBreak = TRUE;
if (rc == RETURN_FAIL)
OutOfMemory = TRUE;
}
else if (global->files || p->type == ST_LINKDIR)
{
--count;
print_bars(global, depth + 1, 0);
PutStr(count ? TEE : ELL);
PutStr(p->name);
switch (p->type)
{
case ST_SOFTLINK:
PutStr(" <sl>");
break;
case ST_LINKDIR:
PutStr(" (dir)");
/* fall through */
case ST_LINKFILE:
PutStr(" <hl>");
}
PutStr("\n");
}
}
p = p->next;
#ifdef LOCKALL
UnLock(remember->lock);
#endif
FreeMem(remember, sizeof(struct nameList));
}
CurrentDir(oldlock);
UnLock(lock);
}
else
{
LONG err = IoErr();
PrintFault(err, dname);
rc = RETURN_ERROR;
}
if (!others)
print_bars(global, depth, 1);
--depth;
FreeDosObject(DOS_FIB, m);
if (UserBreak)
rc = USERBREAK;
if (OutOfMemory)
rc = RETURN_FAIL;
return rc;
}
LONG dirtree(Global *global, char *dirname)
{
struct DosLibrary *DOSBase = global->DOSBase;
LONG rc;
struct DateTime dt;
char day[LEN_DATSTRING], date[LEN_DATSTRING];
if (!global->nohead)
{
DateStamp(&dt.dat_Stamp);
dt.dat_Format = FORMAT_DOS;
dt.dat_Flags = NULL;
dt.dat_StrDay = day;
dt.dat_StrDate = date;
dt.dat_StrTime = NULL;
DateToStr(&dt);
PutStr("Directory tree \"");
PutStr(dirname);
PutStr("\" on ");
PutStr(day);
PutStr(" ");
PutStr(date);
PutStr("\n\n");
}
if ((rc = printdtree(global, dirname, 0)) == USERBREAK)
{
PrintFault(ERROR_BREAK, NULL);
rc = RETURN_WARN;
}
return rc;
}